/*
  ==============================================================================

   This file is part of the JUCE library - "Jules' Utility Class Extensions"
   Copyright 2004-11 by Raw Material Software Ltd.

  ------------------------------------------------------------------------------

   JUCE can be redistributed and/or modified under the terms of the GNU General
   Public License (Version 2), as published by the Free Software Foundation.
   A copy of the license is included in the JUCE distribution, or can be found
   online at www.gnu.org/licenses.

   JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

  ------------------------------------------------------------------------------

   To release a closed-source product which uses JUCE, commercial licenses are
   available: visit www.rawmaterialsoftware.com/juce for more information.

  ==============================================================================
*/


LPDIRECT3DDEVICE9 D3D9Helpers::pd3dDevice = NULL;
D3DXMATRIX D3D9Helpers::D3DProjMatrix;






void D3D9Helpers::clear (const Colour& colour)
{
	pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL,
		D3DCOLOR_COLORVALUE(colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha()), 1.0f, 0 );
}

#if JUCE_USE_D3D9_FIXED_FUNCTION

	void D3D9Helpers::prepareFor2D (const int width, const int height)
	{
		D3DXMatrixOrthoLH( &D3D9Helpers::D3DProjMatrix, (float)width, (float)height, 0, 1 );
		pd3dDevice->SetTransform( D3DTS_PROJECTION, &D3D9Helpers::D3DProjMatrix );
	}

	void D3D9Helpers::setPerspective (float fovy, float aspect, float zNear, float zFar)
	{
		D3DXMatrixPerspectiveFovLH( &D3D9Helpers::D3DProjMatrix, fovy, aspect, zNear, zFar );
		pd3dDevice->SetTransform( D3DTS_PROJECTION, &D3D9Helpers::D3DProjMatrix );
	}

	void D3D9Helpers::applyTransform (const AffineTransform& t)
	{
	}

	void D3D9Helpers::applyMatrix (const float matrixValues[16])
	{
	}

	#if ! JUCE_OPENGL_ES
		void D3D9Helpers::applyMatrix (const double matrixValues[16])
		{		    
		}
	#endif
#endif

void D3D9Helpers::enableScissorTest (const Rectangle<int>& clip)
{
	RECT scissorRect;
	scissorRect.left = clip.getX();
	scissorRect.top = clip.getY();
	scissorRect.right = clip.getX() + clip.getWidth();
	scissorRect.bottom = clip.getY() + clip.getHeight();

	D3D9Helpers::pd3dDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
	D3D9Helpers::pd3dDevice->SetScissorRect( &scissorRect );
}

#if JUCE_USE_D3D9_FIXED_FUNCTION
void D3D9Helpers::drawQuad2D (float x1, float y1,
                                float x2, float y2,
                                float x3, float y3,
                                float x4, float y4,
                                const Colour& colour)
{
	DWORD vertexColor = D3DCOLOR_COLORVALUE(colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha());
	VertexQuadVertex vertex[4];
	vertex[0].pos[0] = x1;
	vertex[0].pos[1] = y1;
	vertex[0].pos[2] = 0;
	vertex[0].pos[3] = 1;
	vertex[0].color = vertexColor;
	vertex[0].uv[0] = 0;
	vertex[0].uv[1] = 0;

	vertex[1].pos[0] = x2;
	vertex[1].pos[1] = y2;
	vertex[1].pos[2] = 0;
	vertex[1].pos[3] = 1;
	vertex[1].color = vertexColor;
	vertex[1].uv[0] = 1.0f;
	vertex[1].uv[1] = 0;

	vertex[2].pos[0] = x3;
	vertex[2].pos[1] = y3;
	vertex[2].pos[2] = 0;
	vertex[2].pos[3] = 1;
	vertex[2].color = vertexColor;
	vertex[2].uv[0] = 0;
	vertex[2].uv[1] = 1.0f;

	vertex[3].pos[0] = x4;
	vertex[3].pos[1] = y4;
	vertex[3].pos[2] = 0;
	vertex[3].pos[3] = 1;
	vertex[3].color = vertexColor;
	vertex[3].uv[0] = 1.0f;
	vertex[3].uv[1] = 1.0f;

	D3D9Helpers::pd3dDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 );
	D3D9Helpers::pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vertex, sizeof( VertexQuadVertex ) );

}

void D3D9Helpers::drawQuad3D (float x1, float y1, float z1,
                                float x2, float y2, float z2,
                                float x3, float y3, float z3,
                                float x4, float y4, float z4,
                                const Colour& colour)
{

	DWORD vertexColor = D3DCOLOR_COLORVALUE(colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha());
	GeoVertex vertex[4];
	vertex[0].pos[0] = x1;
	vertex[0].pos[1] = y1;
	vertex[0].pos[2] = z1;
	vertex[0].color = vertexColor;
	vertex[0].uv[0] = 0;
	vertex[0].uv[1] = 0;

	vertex[1].pos[0] = x2;
	vertex[1].pos[1] = y2;
	vertex[1].pos[2] = z2;
	vertex[1].color = vertexColor;
	vertex[1].uv[0] = 1.0f;
	vertex[1].uv[1] = 0;

	vertex[2].pos[0] = x3;
	vertex[2].pos[1] = y3;
	vertex[2].pos[2] = z3;
	vertex[2].color = vertexColor;
	vertex[2].uv[0] = 0;
	vertex[2].uv[1] = 1.0f;

	vertex[3].pos[0] = x4;
	vertex[3].pos[1] = y4;
	vertex[3].pos[2] = z4;
	vertex[3].color = vertexColor;
	vertex[3].uv[0] = 1.0f;
	vertex[3].uv[1] = 1.0f;

	D3D9Helpers::pd3dDevice->SetFVF( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 );
	D3D9Helpers::pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vertex, sizeof( GeoVertex ) );
}



void D3D9Helpers::drawTextureQuad (const LPDIRECT3DTEXTURE9& D3Dtexture, const Rectangle<int>& rect, const Colour& colour)
{
    const float l = (float) rect.getX();
    const float t = (float) rect.getY();
    const float r = (float) rect.getRight();
    const float b = (float) rect.getBottom();

	DWORD vertexColor = D3DCOLOR_COLORVALUE(colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha());
	VertexQuadVertex vertex[4];
	vertex[0].pos[0] = l;
	vertex[0].pos[1] = t;
	vertex[0].pos[2] = 0;
	vertex[0].pos[3] = 1;
	vertex[0].color = vertexColor;
	vertex[0].uv[0] = 0;
	vertex[0].uv[1] = 0;

	vertex[1].pos[0] = r;
	vertex[1].pos[1] = t;
	vertex[1].pos[2] = 0;
	vertex[1].pos[3] = 1;
	vertex[1].color = vertexColor;
	vertex[1].uv[0] = 1.0f;
	vertex[1].uv[1] = 0;

	vertex[2].pos[0] = l;
	vertex[2].pos[1] = b;
	vertex[2].pos[2] = 0;
	vertex[2].pos[3] = 1;
	vertex[2].color = vertexColor;
	vertex[2].uv[0] = 0;
	vertex[2].uv[1] = 1.0f;

	vertex[3].pos[0] = r;
	vertex[3].pos[1] = b;
	vertex[3].pos[2] = 0;
	vertex[3].pos[3] = 1;
	vertex[3].color = vertexColor;
	vertex[3].uv[0] = 1.0f;
	vertex[3].uv[1] = 1.0f;

	D3D9Helpers::pd3dDevice->SetTexture(0, D3Dtexture);
	D3D9Helpers::pd3dDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 );
	D3D9Helpers::pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vertex, sizeof( VertexQuadVertex ) );
	D3D9Helpers::pd3dDevice->SetTexture(0, NULL);
}

void D3D9Helpers::fillRectWithTexture (const Rectangle<int>& rect, const LPDIRECT3DTEXTURE9& D3Dtexture, const float alpha)
{

	Colour RectColor(alpha, alpha, alpha, alpha);
	D3D9Helpers::pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	D3D9Helpers::pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	D3D9Helpers::pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
	D3D9Helpers::pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
    drawTextureQuad (D3Dtexture, rect, RectColor);
}

void D3D9Helpers::fillRectWithColour (const Rectangle<int>& rect, const Colour& colour)
{
    const float l = (float) rect.getX();
    const float t = (float) rect.getY();
    const float r = (float) rect.getRight();
    const float b = (float) rect.getBottom();

	DWORD vertexColor = D3DCOLOR_COLORVALUE(colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha());
	VertexQuadVertex vertex[4];
	vertex[0].pos[0] = l;
	vertex[0].pos[1] = t;
	vertex[0].pos[2] = 0;
	vertex[0].pos[3] = 1;
	vertex[0].color = vertexColor;
	vertex[0].uv[0] = 0;
	vertex[0].uv[1] = 0;

	vertex[1].pos[0] = r;
	vertex[1].pos[1] = t;
	vertex[1].pos[2] = 0;
	vertex[1].pos[3] = 1;
	vertex[1].color = vertexColor;
	vertex[1].uv[0] = 1.0f;
	vertex[1].uv[1] = 0;

	vertex[2].pos[0] = l;
	vertex[2].pos[1] = b;
	vertex[2].pos[2] = 0;
	vertex[2].pos[3] = 1;
	vertex[2].color = vertexColor;
	vertex[2].uv[0] = 0;
	vertex[2].uv[1] = 1.0f;

	vertex[3].pos[0] = r;
	vertex[3].pos[1] = b;
	vertex[3].pos[2] = 0;
	vertex[3].pos[3] = 1;
	vertex[3].color = vertexColor;
	vertex[3].uv[0] = 1.0f;
	vertex[3].uv[1] = 1.0f;

	D3D9Helpers::pd3dDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_DIFFUSE );
	D3D9Helpers::pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vertex, sizeof( VertexQuadVertex ) );
}

bool D3D9Helpers::LoadD3D9TextureFromFile(LPDIRECT3DTEXTURE9& Texture, const String& TexFilename)
{
	return (S_OK == D3DXCreateTextureFromFile( D3D9Helpers::pd3dDevice, TexFilename.toWideCharPointer(), &Texture ));
}


#endif

//==============================================================================
D3D9TextureFromImage::D3D9TextureFromImage (const Image& image)
    : imageWidth (image.getWidth()),
      imageHeight (image.getHeight())
{

    D3D9FrameBuffer* const fb = D3D9ImageType::getFrameBufferFrom (image);

    if (fb != nullptr)
    {
        D3Dtexture = fb->getTexture();
        fullWidthProportion  = 1.0f;
        fullHeightProportion = 1.0f;
    }
    else
    {
        D3Dtexture_ptr = new D3D9Texture();
        D3Dtexture_ptr->loadImage (image);
        D3Dtexture = D3Dtexture_ptr->getTexture();

        fullWidthProportion  = imageWidth  / (float) D3Dtexture_ptr->getWidth();
        fullHeightProportion = imageHeight / (float) D3Dtexture_ptr->getHeight();
    }
}

D3D9TextureFromImage::~D3D9TextureFromImage() {}
